package edu.ustb.mis.dm.impl.algorithm;

import java.util.ArrayList;
import java.util.List;
import edu.ustb.mis.dm.Constants;
import edu.ustb.mis.dm.interfaces.algorithm.ClusterAlgorithm;
import edu.ustb.mis.dm.model.ClusterResult;

public abstract class AbstractSCABOSFV implements ClusterAlgorithm<ClusterResult> {
	protected List<ClusterResult> instanceList = new ArrayList<ClusterResult>();

	protected List<ClusterResult> clusterResultList = new ArrayList<ClusterResult>();

	protected ClusterResult tmp_clusterResult = new ClusterResult();

	protected double threshhold = Constants.FIRST_THRESHHOLD;

	protected float dissimilarity = 0;

	protected float tmp_dissimilarity = 100;

	protected int tmp_j = 1;

	protected ClusterResult clusterResult;

	protected int category_count;

	protected ClusterResult instance;

	/**
	 * 当差异度小于等于阈值的时候将元素加入现有类别
	 * 
	 * @param clusterResultList
	 */
	protected void addToExist() {
		clusterResult = clusterResultList.get(tmp_j);
		clusterResult.add(instance.getClassIDList(), instance, tmp_dissimilarity);
	}

	/**
	 * 在差异度大于阈值的时候，新建类别并加入元素
	 * 
	 * @param clusterResultList
	 * @param instanceList
	 * @param i
	 */
	protected void addToNew(final int i) {
		instance = instanceList.get(i);
		clusterResultList.add(instance);
	}

	/**
	 * 计算两个元素间的差异度
	 * 
	 * @param j
	 */
	protected float calculateDissimilarity(final int j) {
		clusterResult = clusterResultList.get(j);
		tmp_clusterResult.clearSet();
		tmp_clusterResult.init(clusterResult.getSameSet(), clusterResult.getAllSet());
		tmp_clusterResult.contrast(instance);
		return (tmp_clusterResult.diffSize()) / (tmp_clusterResult.sameSize() * clusterResult.nextSize(instance));
	}

	/**
	 * CABOSFV聚类的主要方法
	 * 
	 * @param coefficient
	 * @param instanceList
	 * @return
	 */
	public List<ClusterResult> cluster() {
		final int instanceListSize = instanceList.size();
		instance = instanceList.get(0);
		clusterResultList.add(instance);
		for (int i = 1; i < instanceListSize; i++) {
			instance = instanceList.get(i);
			category_count = clusterResultList.size();
			for (int j = 0; j < category_count; j++) {
				dissimilarity = calculateDissimilarity(j);// 计算差异度
				if (dissimilarity < tmp_dissimilarity) {
					tmp_j = j;
					tmp_dissimilarity = dissimilarity;
				}
			}
			if (tmp_dissimilarity <= threshhold) {
				// 小于阈值是加入到现有类
				this.addToExist();
				tmp_dissimilarity = 100;
			} else {
				// 大于阈值时新建类
				this.addToNew(i);
			}
		}
		return clusterResultList;
	}

	public List<ClusterResult> getInstanceList() {
		return instanceList;
	}

	public List<ClusterResult> getResultList() {
		return clusterResultList;
	}

	public void setThreshhold(final double threshhold) {
		this.threshhold = threshhold;
	}
}
